package resman.model;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

@SuppressWarnings("serial")
public class Property implements Serializable
{
	/** Classe da propriedade */
	private Class<?> cl;
	
	/** Método get */
	private Method getMethod;
	
	/** Método set */
	private Method setMethod;
	
	/**
	 * Constrói uma propriedade
	 * @param name Nome da propriedade
	 * @param cl Classe que contém a propriedade
	 */
	public Property(String name, Class<?> cl) throws PropertyException
	{
		Method[] ms = cl.getDeclaredMethods();
		for (Method m : ms)
		{
			if (m.getName().equals("get" + toUpper(name)))
				getMethod = m;
			else if (m.getName().equals("set" + toUpper(name)))
				setMethod = m;
		}
		
		if (getMethod == null)
			throw new PropertyException();
		
		this.cl = getMethod.getReturnType();
	}
	
	/**
	 * Transforma o primeiro caracter da string em caixa baixa
	 * @param name String
	 * @return String com primeiro caracter em caixa baixa
	 */
	public static String toLower(String name)
	{
		return Character.toLowerCase(name.charAt(0)) + name.substring(1);
	}
	
	/**
	 * Transforma o primeiro caracter da string em caixa alta
	 * @param name String
	 * @return String com primeiro caracter em caixa alta
	 */
	public static String toUpper(String name)
	{
		return Character.toUpperCase(name.charAt(0)) + name.substring(1);
	}
	
	/**
	 * Retorna o formato da data
	 * @return Formato da data
	 */
	protected static DateFormat getDateFormat()
	{
		return new SimpleDateFormat("dd/MM/yyyy");
	}
	
	/**
	 * Transforma um tipo date para string
	 * @param date Data
	 * @return Formato string
	 */
	public static String toString(Date date)
	{
		return getDateFormat().format(date);
	}
	
	/**
	 * Seta o valor da propriedade
	 * @param obj Objeto que contém a propriedade
	 * @param value Valor da propriedade
	 */
	public void set(Object obj, String value) throws PropertyException
	{
		try
		{
			if (cl == Date.class)
				setMethod.invoke(obj, getDateFormat().parse(value));
			else if (cl == Integer.class || cl == int.class)
				setMethod.invoke(obj, Integer.parseInt(value));
			else if (cl == Float.class || cl == float.class)
				setMethod.invoke(obj, Float.parseFloat(value));
			else if (cl == Boolean.class || cl == boolean.class)
				setMethod.invoke(obj, value != null);
			else
				setMethod.invoke(obj, value);
		}
		catch (Exception ex)
		{
			throw new PropertyException(ex);
		}
	}
	
	/**
	 * Retorna o valor da propriedade
	 * @param obj Objeto que contém a propriedade
	 * @return Valor da propriedade
	 */
	public String get(Object obj) throws PropertyException
	{
		try
		{
			Object ret = getMethod.invoke(obj);
			
			if (cl == Date.class)
				return getDateFormat().format((Date) ret);
			else
				return ret.toString();
		}
		catch (Exception ex)
		{
			throw new PropertyException(ex);
		}
	}
}
